home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 Extra Demos / Wrapping Illustration / Illustration.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-19  |  23.4 KB  |  821 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. // Illustration.c
  3. //
  4. // By Vern Jensen, January 1996
  5. ///--------------------------------------------------------------------------------------
  6.  
  7.  
  8. #include <SWIncludes.h>
  9. #include <SWGameUtils.h>
  10.  
  11. #include "SWApplication.h"
  12. #include "Illustration.h"
  13.  
  14.  
  15. #define kMaxFPS                        30        // set to 0 for maximum speed
  16. #define    kSpriteMoveDelta            5        // speed of the sprite you control
  17. #define kStartRow                    1        // starting location of your sprite
  18. #define kStartCol                    1
  19.  
  20. #define kDiamondFrameRate            10        // How often diamond tiles change frames
  21.  
  22. #define kNumIdleSprites                4
  23. #define kNumBallSprites                80
  24. #define    kMaxSpriteMoveDelta            2
  25.  
  26. #define kTileWidth                    40
  27. #define kTileHeight                    40
  28. #define kTileMapRows                36
  29. #define kTileMapCols                32
  30.  
  31. #define kFollowSpriteMargin            0        // Distance sprite can get to edge of screen
  32.  
  33.  
  34. #define    kLeftArrowKey                0x7B
  35. #define    kRightArrowKey                0x7C
  36. #define    kDownArrowKey                0x7D
  37. #define    kUpArrowKey                    0x7E
  38.  
  39. #define    kLeftKeyPad                    0x56
  40. #define    kRightKeyPad                0x58
  41. #define    kDownKeyPad                    0x54
  42. #define    kUpKeyPad                    0x5B
  43.  
  44. #define kEscKey                        0x35
  45.  
  46.  
  47. enum tileIDs
  48. {
  49.     kGrassTile,
  50.     kWallTile,
  51.     kBlackTile,
  52.     kDiamondTile,
  53.     kDiamondTile2,
  54.     kLastDiamondTile,
  55.     kMaxNumTiles
  56. };
  57.  
  58.  
  59. /***********/
  60. /* Globals */
  61. /***********/
  62.  
  63. SpriteWorldPtr        gSpriteWorldP;
  64. FramePtr            gMyWindowFrameP;    // WindowFrameP for the bottom area of the screen
  65. TileMapStructPtr    gTileMapStructP;
  66. TileMapPtr            gTileMap;
  67. SpritePtr            gSimpleSpriteP;
  68. WindowPtr            gWindowP;
  69. Rect                gOffscreenRect, gScreenRect, gMoveBoundsRect;
  70. short                gPenSize = 1;
  71.  
  72. struct moveKeys        // Keeps track of which keys are up and which are down
  73. {
  74.     Boolean    up;
  75.     Boolean    right;
  76.     Boolean    down;
  77.     Boolean    left;
  78. } keys;
  79.  
  80.  
  81.     // Below is our "hard-coded" maze data. Not the best way to store TileMap data,
  82.     // but this was done before I made the SWSaveTileMap and SWLoadTileMap routines.
  83.     // I decided to leave it this way to demonstrate how to load a "hard-coded" TileMap.
  84. short            gMazeData[kTileMapRows][kTileMapCols] = {
  85. {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},    // 0
  86. {1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1},    // 1
  87. {1,0,0,0,0,0,0,0,1,0,1,0,0,0,1,1,1,1,1,0,0,0,1,0,0,1,1,1,1,1,0,1},    // 2
  88. {1,0,0,0,0,0,0,0,1,0,1,0,1,1,1,0,0,0,1,1,1,0,1,0,1,1,1,3,0,1,0,1},    // 3
  89. {1,1,1,1,1,1,0,1,1,0,1,0,0,0,0,0,1,0,1,1,3,0,1,0,0,0,1,1,0,1,0,1},    // 4
  90. {1,1,3,1,0,0,0,0,0,0,1,1,0,1,1,1,1,0,0,1,1,1,1,0,1,0,1,1,0,1,0,1},    // 5
  91. {1,0,0,1,0,1,0,1,1,1,1,0,0,1,3,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,1},    // 6
  92. {1,0,1,1,0,1,0,0,1,0,0,0,1,1,1,0,0,1,0,1,0,0,0,1,1,1,1,1,1,1,0,1},    // 7
  93. {1,0,0,0,0,1,1,0,1,0,1,1,1,3,1,1,0,1,0,1,1,1,0,0,1,0,0,0,1,0,0,1},    // 8
  94. {1,1,1,1,1,1,0,0,1,0,0,0,0,0,1,0,0,1,0,1,3,1,1,0,1,0,1,0,1,0,1,1},    // 9
  95. {1,0,0,0,0,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,1,0,0,0,1,0,1,0,0,1},    // 10
  96. {1,0,1,1,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,1,1,1,1,0,1,1,0,1},    // 11
  97. {1,0,0,1,0,0,0,0,0,1,0,1,0,1,1,1,1,0,1,1,1,0,0,0,1,0,0,0,1,0,0,1},    // 12
  98. {1,1,0,1,1,1,1,1,1,1,0,1,0,1,3,1,0,0,1,3,1,1,1,0,0,0,1,0,1,0,1,1},    // 13
  99. {1,0,0,1,0,0,3,1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0,1,0,0,1},    // 14
  100. {1,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,0,1,1,0,1},    // 15
  101. {1,0,1,0,0,1,1,0,0,1,0,0,0,1,3,1,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,1},    // 16
  102. {1,0,0,0,1,1,1,0,1,1,0,1,0,0,0,1,0,1,1,0,0,0,1,1,1,1,1,0,0,0,1,1},    // 17
  103. {1,0,1,1,1,1,1,0,0,0,0,1,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,1},    // 18
  104. {1,0,1,3,0,0,1,1,1,1,1,1,0,0,0,1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,0,1},    // 19
  105. {1,0,1,1,1,0,1,0,0,0,0,1,0,1,0,1,0,1,1,0,1,3,1,0,0,0,0,0,0,1,0,1},    // 20
  106. {1,0,1,1,0,0,1,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,1,0,0,0,1},    // 21
  107. {1,0,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,1,0,1},    // 22
  108. {1,0,1,0,1,1,0,0,1,0,0,1,0,0,0,1,0,0,0,3,1,1,0,0,1,0,1,1,1,0,0,1},    // 23
  109. {1,0,1,0,0,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1},    // 24
  110. {1,0,1,1,0,1,0,0,1,0,0,0,0,1,3,0,1,1,3,1,3,1,1,1,0,1,1,0,1,1,1,1},    // 25
  111. {1,0,0,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,1,0,0,0,1,0,0,1,1,1,1},    // 26
  112. {1,1,0,0,0,1,0,0,1,0,0,1,0,0,1,1,0,1,0,1,0,1,0,1,1,1,3,1,1,1,1,1},    // 27
  113. {1,1,1,1,1,1,0,1,1,1,0,1,1,0,0,0,0,1,0,1,0,0,0,1,1,1,1,1,0,0,0,1},    // 28
  114. {1,0,0,0,0,0,0,1,3,1,0,0,1,0,1,1,1,1,0,1,1,1,1,1,0,0,0,1,0,1,0,1},    // 29
  115. {1,0,1,1,1,1,0,1,0,1,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,1,3,1},    // 30
  116. {1,0,0,1,0,0,0,1,0,1,0,0,1,1,1,1,1,0,1,0,0,0,1,0,1,1,1,1,1,1,1,1},    // 31
  117. {1,1,0,1,0,1,1,1,0,1,0,1,1,0,0,0,1,3,1,1,1,1,1,0,0,1,3,3,3,3,3,1},    // 32
  118. {1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,1,1,1,0,0,0,1,1,0,0,3,3,3,3,3,1},    // 33
  119. {1,3,1,1,0,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,1,0,3,1,1,1,3,3,3,3,3,1},    // 34
  120. {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}    // 35
  121. };
  122.  
  123.  
  124.  
  125.  
  126. ///--------------------------------------------------------------------------------------
  127. // Main
  128. ///--------------------------------------------------------------------------------------
  129.  
  130. void    main( void )
  131. {
  132.     Initialize(kNumberOfMoreMastersCalls);
  133.     Randomize();
  134.     
  135.     if (SWHasSystem7())
  136.     {
  137.         AllowKeyUpEvents();    // Part of SWGameUtils.c
  138.         SetCursor(*GetCursor(watchCursor));
  139.         
  140.         CreateSpriteWorld();
  141.         CreateSprites();
  142.         
  143.         SetCursor(&qd.arrow);
  144.         HideCursor();
  145.         
  146.         SetUpAnimation();
  147.         RunAnimation();
  148.         ShutDown();
  149.         
  150.         RestoreEventMask();    // Call this after AllowKeyUpEvents
  151.     }
  152.     else
  153.     {
  154.         CantRunOnThisMachine();
  155.     }
  156. }
  157.  
  158.  
  159. ///--------------------------------------------------------------------------------------
  160. // CreateSpriteWorld
  161. ///--------------------------------------------------------------------------------------
  162.  
  163. void    CreateSpriteWorld( void )
  164. {
  165.     RgnHandle    mBarUpdateRgn;
  166.     Rect        windRect;
  167.     OSErr        err;
  168.     short        row, col;
  169.     
  170.     gWindowP = GetNewCWindow(kWindowResID, NULL, (WindowPtr)-1L);
  171.     
  172.     if (gWindowP != NULL)
  173.     {
  174.             // Center window in screen
  175.         windRect = gWindowP->portRect;
  176.         CenterRect(&windRect, &qd.screenBits.bounds);
  177.         MoveWindow(gWindowP, windRect.left, windRect.top, false);
  178.         
  179.         ShowWindow(gWindowP);
  180.         SetPort(gWindowP);
  181.         mBarUpdateRgn = SWHideMenuBar(gWindowP); // Must be done *after* showing window!
  182.         EraseRgn(mBarUpdateRgn);
  183.     }
  184.     else
  185.         CantFindResource();
  186.     
  187.     
  188.     err = SWEnterSpriteWorld();
  189.     FatalError(err);
  190.     
  191.     
  192.         // Set size of screenRect and offscreenRect
  193.     gScreenRect = gWindowP->portRect;
  194.     OffsetRect(&gScreenRect, -gScreenRect.left, -gScreenRect.top);    // Offset to 0,0
  195.  
  196.     gScreenRect.left += kTileWidth/2;
  197.     gScreenRect.right -= kTileWidth/2;
  198.     gOffscreenRect = gScreenRect;
  199.     
  200.     gScreenRect.top += kTileHeight/4;
  201.     gScreenRect.bottom = gScreenRect.bottom/2 - kTileHeight/4;     // Set to top half
  202.     gOffscreenRect.top = gOffscreenRect.bottom/2 + kTileHeight/4; // Set to bottom half
  203.     gOffscreenRect.bottom -= kTileHeight/4;
  204.  
  205.     
  206.         // Create the scrolling sprite world
  207.     err = SWCreateSpriteWorldFromWindow(&gSpriteWorldP, (CWindowPtr)gWindowP, 
  208.             &gScreenRect, &gOffscreenRect, 0);
  209.     FatalError(err);
  210.     
  211.         // Create windowFrame for the bottom area of the screen that shows the work area
  212.     SetPort(gWindowP);
  213.     err = SWCreateWindowFrame(&gMyWindowFrameP, &gOffscreenRect, 0);
  214.     FatalError(err);
  215.     
  216.     SWLockWindowFrame(gMyWindowFrameP);    // Very important!
  217.  
  218.  
  219.     err = SWInitTiling(gSpriteWorldP, kTileHeight, kTileWidth, kMaxNumTiles);
  220.     FatalError(err);
  221.     
  222.     err = SWCreateTileMap(&gTileMapStructP, kTileMapRows, kTileMapCols);
  223.     FatalError(err);
  224.     
  225.     SWInstallTileMap(gSpriteWorldP, gTileMapStructP, 0);
  226.     gTileMap = gTileMapStructP->tileMap;
  227.  
  228.  
  229.         // Load B&W dithered tiles
  230.     if (gSpriteWorldP->pixelDepth == 1)
  231.     {
  232.         err = SWLoadTilesFromPictResource(
  233.             gSpriteWorldP, 
  234.             0,                // startTileID 
  235.             kMaxNumTiles-1, // endTileID
  236.             129,            // pictResID
  237.             0,                // maskResID
  238.             kNoMask,        // maskType
  239.             1,                // horizBorderWidth
  240.             1);                // vertBorderHeight
  241.     }
  242.     else    // Load 256 color tiles
  243.     {
  244.         err = SWLoadTilesFromPictResource(
  245.             gSpriteWorldP, 
  246.             0,                // startTileID 
  247.             kMaxNumTiles-1, // endTileID
  248.             128,            // pictResID
  249.             0,                // maskResID
  250.             kNoMask,        // maskType
  251.             1,                // horizBorderWidth
  252.             1);                // vertBorderHeight
  253.     }
  254.     FatalError(err);
  255.     
  256.     
  257.         // Copy maze data into tileMap
  258.     for (row = 0; row < kTileMapRows; row++)
  259.     {
  260.         for (col = 0; col < kTileMapCols; col++)
  261.         {
  262.             gTileMap[row][col] = gMazeData[row][col];
  263.         }
  264.     }
  265.     
  266.     
  267.         // movement boundary = size of tileMap
  268.     SetRect(&gMoveBoundsRect, 0, 0, kTileMapCols * kTileWidth, kTileMapRows * kTileHeight);
  269. }
  270.     
  271.     
  272. ///--------------------------------------------------------------------------------------
  273. // CreateSprites
  274. ///--------------------------------------------------------------------------------------
  275.  
  276. void    CreateSprites( void )
  277. {
  278.     SpriteLayerPtr        mainSpriteLayerP;
  279.     SpriteLayerPtr        ballSpriteLayerP;
  280.     SpriteLayerPtr        idleSpriteLayerP;
  281.     SpritePtr            spriteP;
  282.     SpritePtr            idleSpriteP;
  283.     short                spriteNum;
  284.     Point                moveDelta;
  285.     OSErr                err;
  286.     
  287.     
  288.         // Create the sprite layers
  289.     err = SWCreateSpriteLayer(&mainSpriteLayerP);
  290.     FatalError(err);
  291.     err = SWCreateSpriteLayer(&ballSpriteLayerP);
  292.     FatalError(err);
  293.     err = SWCreateSpriteLayer(&idleSpriteLayerP);
  294.     FatalError(err);
  295.     
  296.     
  297.         // Create the main sprite
  298.     err = SWCreateSpriteFromCicnResource(gSpriteWorldP, &gSimpleSpriteP, NULL, 
  299.             128, 1, kFatMask);    
  300.     FatalError(err);
  301.     
  302.             // Set up the main sprite
  303.     SWAddSprite(mainSpriteLayerP, gSimpleSpriteP);
  304.     SWSetSpriteMoveProc(gSimpleSpriteP, KeySpriteMoveProc);
  305.     SWSetSpriteLocation(gSimpleSpriteP, kStartCol * kTileWidth, kStartRow * kTileHeight);
  306.     if (gSpriteWorldP->pixelDepth == 8)        // If in 256 colors
  307.         SWSetSpriteDrawProc(gSimpleSpriteP, BlitPixie8BitRectDrawProc);
  308.     
  309.         
  310.  
  311.         // create and set up the idle sprites
  312.     for (spriteNum = 0; spriteNum < kNumIdleSprites; spriteNum++)
  313.     {
  314.         if (spriteNum == 0)
  315.         {
  316.             err = SWCreateSpriteFromCicnResource(gSpriteWorldP, &idleSpriteP, NULL, 
  317.                     129, 1, kFatMask);    
  318.             FatalError(err);
  319.             spriteP = idleSpriteP;
  320.         }
  321.         else
  322.         {        // Clone from first sprite
  323.             err = SWCloneSprite(idleSpriteP, &spriteP, NULL);
  324.             FatalError(err);
  325.         }
  326.         
  327.         SWAddSprite(idleSpriteLayerP, spriteP);
  328.         
  329.         SWSetSpriteLocation(spriteP, (3 + spriteNum) * kTileWidth + kTileWidth/2, 
  330.                             kTileHeight * 2);
  331.  
  332.         if (gSpriteWorldP->pixelDepth == 8)        // If in 256 colors
  333.             SWSetSpriteDrawProc(spriteP, BlitPixie8BitMaskDrawProc);
  334.     }
  335.     
  336.     
  337.         // create and set up the ball sprites
  338.     for (spriteNum = 0; spriteNum < kNumBallSprites; spriteNum++)
  339.     {
  340.         err = SWCloneSprite(idleSpriteP, &spriteP, NULL);
  341.         FatalError(err);
  342.         
  343.         SWAddSprite(ballSpriteLayerP, spriteP);
  344.         SWSetSpriteMoveBounds(spriteP, &gMoveBoundsRect);
  345.         SWSetSpriteMoveProc(spriteP, BallSpriteMoveProc);
  346.         
  347.         SWSetSpriteLocation(spriteP, 
  348.                 GetRandom(0, gMoveBoundsRect.right), 
  349.                 GetRandom(0, gMoveBoundsRect.bottom));
  350.         
  351.         do
  352.         {
  353.             moveDelta.h = GetRandom(-kMaxSpriteMoveDelta, kMaxSpriteMoveDelta);
  354.             moveDelta.v = GetRandom(-kMaxSpriteMoveDelta, kMaxSpriteMoveDelta);
  355.         } while (!moveDelta.v && !moveDelta.h);
  356.         
  357.         SWSetSpriteMoveDelta(spriteP, moveDelta.h, moveDelta.v);
  358.         
  359.         if (gSpriteWorldP->pixelDepth == 8)        // If in 256 colors
  360.             SWSetSpriteDrawProc(spriteP, BlitPixie8BitMaskDrawProc);
  361.     }
  362.  
  363.     
  364.     
  365.     SWAddSpriteLayer(gSpriteWorldP, mainSpriteLayerP);
  366.     SWAddSpriteLayer(gSpriteWorldP, idleSpriteLayerP);
  367.     SWAddSpriteLayer(gSpriteWorldP, ballSpriteLayerP);
  368.     
  369.     SWLockSpriteWorld(gSpriteWorldP);
  370. }
  371.  
  372.  
  373. ///--------------------------------------------------------------------------------------
  374. // SetUpAnimation
  375. ///--------------------------------------------------------------------------------------
  376.  
  377. void    SetUpAnimation( void )
  378. {
  379.     SWSetSpriteWorldMaxFPS(gSpriteWorldP, kMaxFPS);
  380.     SWSetPostDrawCallBack(gSpriteWorldP, MyPostDrawCallBack);
  381.     SWSetScrollingWorldMoveProc(gSpriteWorldP, FollowSpriteMoveProc, gSimpleSpriteP);
  382.     SWSetScrollingWorldMoveBounds(gSpriteWorldP, &gMoveBoundsRect);
  383.     
  384.     SWSetTileChangeProc(gSpriteWorldP, TileChangeProc);
  385.  
  386.     if (gSpriteWorldP->pixelDepth == 8)        // If in 256 colors
  387.     {
  388.         SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, BlitPixie8BitRectDrawProc);
  389.         SWSetDoubleRectDrawProc(gSpriteWorldP, BlitPixie8BitDoubleRectDrawProc);
  390.     }
  391.     else if (gSpriteWorldP->pixelDepth == 16)    // If in thousands of colors
  392.     {
  393.         SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, BlitPixieAllBitRectDrawProc);
  394.         SWSetDoubleRectDrawProc(gSpriteWorldP, BlitPixie16BitDoubleRectDrawProc);
  395.     }
  396.     
  397.     ForeColor(blackColor);
  398.     BackColor(whiteColor);
  399.     
  400.     SWDrawTilesInBackground(gSpriteWorldP);
  401.     SWUpdateScrollingSpriteWorld(gSpriteWorldP, true);
  402. }
  403.  
  404.  
  405. ///--------------------------------------------------------------------------------------
  406. //  RunAnimation
  407. ///--------------------------------------------------------------------------------------
  408.  
  409. void    RunAnimation( void )
  410. {
  411.     FatalError( SWStickyError() ); // Make sure no errors got past us during setup
  412.  
  413.     while (!Button())
  414.     {
  415.         SWProcessScrollingSpriteWorld(gSpriteWorldP);
  416.         FatalError( SWStickyError() );     // Make sure no error occurred during a MoveProc, etc.
  417.         SWAnimateScrollingSpriteWorld(gSpriteWorldP);
  418.         
  419.         if (gSpriteWorldP->frameHasOccurred)
  420.         {
  421.                 // Erase color-coded rects from previous frame
  422.             SWFlagScrollingRectAsChanged(gSpriteWorldP, &gSpriteWorldP->visScrollRect);
  423.             
  424.             
  425.                 // Copy the work area to the bottom portion of the window
  426.             (*gSpriteWorldP->screenDrawProc)(gSpriteWorldP->workFrameP, 
  427.                                              gMyWindowFrameP, 
  428.                                              &gSpriteWorldP->backRect, 
  429.                                              &gMyWindowFrameP->frameRect);
  430.         }
  431.     }
  432.     
  433.     SWShowMenuBar(gWindowP);
  434. }
  435.  
  436.  
  437. ///--------------------------------------------------------------------------------------
  438. //  ShutDown (clean up and dispose of the SpriteWorld)
  439. ///--------------------------------------------------------------------------------------
  440.  
  441. void    ShutDown( void )
  442. {
  443.     SWUnlockSpriteWorld(gSpriteWorldP);
  444.     SWDisposeSpriteWorld(&gSpriteWorldP);
  445.     SWExitSpriteWorld();
  446.     
  447.     FlushEvents(everyEvent, 0);
  448.     ShowCursor();
  449. }
  450.  
  451.  
  452. ///--------------------------------------------------------------------------------------
  453. //  TileChangeProc
  454. ///--------------------------------------------------------------------------------------
  455.  
  456. SW_FUNC void TileChangeProc(
  457.     SpriteWorldPtr spriteWorldP)
  458. {
  459.     short            curImage;
  460.     static short    wallDelay = 0, diamondDelay = 0;
  461.     static short    oldTicks = 0;
  462.     short            ticksPassed, ticks;
  463.     
  464.         // Initialize oldTicks the first time this function is called
  465.     if (oldTicks == 0)
  466.         oldTicks = TickCount();
  467.     
  468.     ticks = TickCount();
  469.     ticksPassed = ticks - oldTicks;        // Number of ticks passed since last call
  470.     oldTicks = ticks;
  471.     
  472.     
  473.         // kDiamondTile
  474.     diamondDelay += ticksPassed;
  475.     if (diamondDelay >= kDiamondFrameRate)
  476.     {
  477.         curImage = spriteWorldP->curTileImage[kDiamondTile];
  478.         if (curImage < kLastDiamondTile)
  479.             curImage++;
  480.         else
  481.             curImage = kDiamondTile;
  482.         
  483.         SWChangeTileImage(spriteWorldP, kDiamondTile, curImage);
  484.         diamondDelay = 0;
  485.     }
  486. }
  487.  
  488.  
  489. ///--------------------------------------------------------------------------------------
  490. //  KeySpriteMoveProc
  491. ///--------------------------------------------------------------------------------------
  492.  
  493. SW_FUNC void KeySpriteMoveProc(SpritePtr srcSpriteP)
  494. {
  495.     short    row, col;
  496.     short    rowDelta, colDelta;
  497.     short    tile;
  498.     
  499.     UpdateKeys();    // Put the latest key values in the keys structure
  500.     
  501.     
  502.     row = srcSpriteP->destFrameRect.top / kTileHeight;
  503.     col = srcSpriteP->destFrameRect.left / kTileWidth;
  504.     
  505.     if (row * kTileHeight == srcSpriteP->destFrameRect.top &&
  506.         col * kTileWidth == srcSpriteP->destFrameRect.left)
  507.     {
  508.             // Set tile below sprite to blank
  509.         if (gTileMap[row][col] != kBlackTile)
  510.             SWDrawTile(gSpriteWorldP, 0, row, col, kBlackTile);
  511.         
  512.         rowDelta = 0;
  513.         colDelta = 0;
  514.         
  515.         if (keys.left)
  516.             colDelta = -1;
  517.         else if (keys.right)
  518.             colDelta = 1;
  519.         else if (keys.up)
  520.             rowDelta = -1;
  521.         else if (keys.down)
  522.             rowDelta = 1;
  523.         
  524.         
  525.         tile = gTileMap[row + rowDelta][col + colDelta];
  526.         
  527.         if (tile != kWallTile)
  528.         {
  529.             srcSpriteP->vertMoveDelta = rowDelta * kSpriteMoveDelta;
  530.             srcSpriteP->horizMoveDelta = colDelta * kSpriteMoveDelta;
  531.         }
  532.         else
  533.         {
  534.             srcSpriteP->vertMoveDelta = 0;
  535.             srcSpriteP->horizMoveDelta = 0;
  536.         }
  537.     }
  538.     
  539.     SWOffsetSprite(srcSpriteP, srcSpriteP->horizMoveDelta, srcSpriteP->vertMoveDelta);
  540. }
  541.  
  542.  
  543. ///--------------------------------------------------------------------------------------
  544. //  BallSpriteMoveProc - moveProc for all the bouncing balls
  545. ///--------------------------------------------------------------------------------------
  546.  
  547. SW_FUNC void BallSpriteMoveProc(SpritePtr ballSpriteP)
  548. {    
  549.     SWOffsetSprite(ballSpriteP, ballSpriteP->horizMoveDelta, ballSpriteP->vertMoveDelta);
  550.     SWBounceSprite(ballSpriteP);
  551. }
  552.  
  553.  
  554. ///--------------------------------------------------------------------------------------
  555. //  FollowSpriteMoveProc - our scrolling WorldMoveProc
  556. ///--------------------------------------------------------------------------------------
  557.  
  558. SW_FUNC void FollowSpriteMoveProc(
  559.     SpriteWorldPtr spriteWorldP,
  560.     SpritePtr followSpriteP)
  561. {    
  562.     Rect*    visScrollRectP = &spriteWorldP->visScrollRect;
  563.     short    hMargin = (spriteWorldP->windRect.right - spriteWorldP->windRect.left)/3;
  564.     short    vMargin = (spriteWorldP->windRect.bottom - spriteWorldP->windRect.top)/3;
  565.     
  566.     
  567.         // Move horizontally
  568.     if (followSpriteP->destFrameRect.right > visScrollRectP->right - hMargin)
  569.     {
  570.         spriteWorldP->horizScrollDelta = followSpriteP->destFrameRect.right - 
  571.                 (visScrollRectP->right - hMargin);
  572.     }
  573.     else if (followSpriteP->destFrameRect.left < visScrollRectP->left + hMargin)
  574.     {
  575.         spriteWorldP->horizScrollDelta = followSpriteP->destFrameRect.left - 
  576.                 (visScrollRectP->left + hMargin);
  577.     }
  578.     else
  579.         spriteWorldP->horizScrollDelta = 0;
  580.     
  581.     
  582.         // Move vertically
  583.     if (followSpriteP->destFrameRect.bottom > visScrollRectP->bottom - vMargin)
  584.     {
  585.         spriteWorldP->vertScrollDelta = followSpriteP->destFrameRect.bottom - 
  586.                     (visScrollRectP->bottom - vMargin);
  587.     }
  588.     else if (followSpriteP->destFrameRect.top < visScrollRectP->top + vMargin)
  589.     {
  590.         spriteWorldP->vertScrollDelta = followSpriteP->destFrameRect.top - 
  591.                     (visScrollRectP->top + vMargin);
  592.     }
  593.     else
  594.         spriteWorldP->vertScrollDelta = 0;
  595. }
  596.  
  597.  
  598. ///--------------------------------------------------------------------------------------
  599. //  UpdateKeys (Put the latest key values in the keys structure)
  600. ///--------------------------------------------------------------------------------------
  601.  
  602. void    UpdateKeys( void )
  603. {
  604.     EventRecord        event;
  605.     short            theKey, theChar;
  606.     Boolean            isDown;
  607.     
  608.     while ( GetOSEvent( (keyUpMask | keyDownMask), &event ) )
  609.     {
  610.         theKey = (event.message & keyCodeMask) >> 8;
  611.         theChar = (event.message & charCodeMask);
  612.         isDown = (event.what != keyUp);
  613.         
  614.         if ( (theKey == kLeftArrowKey) || (theKey == kLeftKeyPad) )
  615.             keys.left = isDown;
  616.         else if ( (theKey == kRightArrowKey) || (theKey == kRightKeyPad) )
  617.             keys.right = isDown;
  618.         else if ( (theKey == kDownArrowKey) || (theKey == kDownKeyPad) )
  619.             keys.down = isDown;
  620.         else if ( (theKey == kUpArrowKey) || (theKey == kUpKeyPad) )
  621.             keys.up = isDown;
  622.         else if (theChar >= '0' && theChar <= '5' && theKey < 0x52)
  623.         {
  624.             gPenSize = theChar - '0';    // Change thickness of rects
  625.         }
  626.         else if (theKey == kEscKey)        // Go back to beginning of maze
  627.         {
  628.             SWMoveSprite(gSimpleSpriteP, kStartCol * kTileWidth, kStartRow * kTileHeight);
  629.             SWMoveVisScrollRect(gSpriteWorldP, 0, 0);
  630.         }
  631.     }
  632. }
  633.  
  634.  
  635. ///--------------------------------------------------------------------------------------
  636. //    MyPostDrawCallBack - draws outline rects in work area to show where the "pieces"
  637. //    have been copied from in the offscreen area.
  638. ///--------------------------------------------------------------------------------------
  639.  
  640. SW_FUNC void MyPostDrawCallBack(SpriteWorldPtr spriteWorldP)
  641. {    
  642.     FramePtr    srcFrameP = spriteWorldP->workFrameP;
  643.     Rect        visRect = spriteWorldP->windowFrameP->frameRect;
  644.     Rect        srcRect = spriteWorldP->offscreenScrollRect;
  645.     Rect        tempSrcRect;
  646.     
  647.                 // Size of area that was clipped in source rect
  648.     short    topClip=0, rightClip=0, bottomClip=0, leftClip=0;
  649.     
  650.     
  651.         // Clip the source rect, and save what we clipped for wrapping later //
  652.     
  653.         // clip off the top
  654.     if (srcRect.top < srcFrameP->frameRect.top)
  655.     {
  656.         topClip = srcFrameP->frameRect.top - srcRect.top;
  657.         srcRect.top += topClip;    
  658.     }
  659.     
  660.         // clip off the bottom
  661.     if (srcRect.bottom > srcFrameP->frameRect.bottom)
  662.     {
  663.         bottomClip = srcRect.bottom - srcFrameP->frameRect.bottom;
  664.         srcRect.bottom -= bottomClip;
  665.     }
  666.     
  667.         // clip off the left
  668.     if (srcRect.left < srcFrameP->frameRect.left)
  669.     {
  670.         leftClip = srcFrameP->frameRect.left - srcRect.left;
  671.         srcRect.left += leftClip;
  672.     }
  673.     
  674.         // clip off the right
  675.     if (srcRect.right > srcFrameP->frameRect.right)
  676.     {
  677.         rightClip = srcRect.right - srcFrameP->frameRect.right;
  678.         srcRect.right -= rightClip;
  679.     }
  680.     
  681.     
  682.     SWSetPortToWorkArea(spriteWorldP);
  683.     PenSize(gPenSize, gPenSize);        // Width of rectangles
  684.     
  685.     
  686.                     // Do the wrapping and drawing //
  687.     
  688.         // Draw left side, starting at top and going down //
  689.     
  690.     if (leftClip)
  691.     {
  692.         if (topClip)    // Draw top-left piece //
  693.         {
  694.             ForeColor(blackColor);
  695.             
  696.                 // Wrap source rect to lower-right corner //
  697.             tempSrcRect.bottom = srcFrameP->frameRect.bottom;
  698.             tempSrcRect.right = srcFrameP->frameRect.right;
  699.             tempSrcRect.top = srcFrameP->frameRect.bottom - topClip;
  700.             tempSrcRect.left = srcFrameP->frameRect.right - leftClip;
  701.             
  702.             FrameRect(&tempSrcRect);
  703.         }
  704.         
  705.         
  706.             // Draw left middle section //
  707.         
  708.         ForeColor(redColor);
  709.         
  710.             // Wrap source rect to right side //
  711.         tempSrcRect.top = srcRect.top;                // Copy clipped source rect
  712.         tempSrcRect.bottom = srcRect.bottom;
  713.         tempSrcRect.right = srcFrameP->frameRect.right;
  714.         tempSrcRect.left = srcFrameP->frameRect.right - leftClip;
  715.         
  716.         FrameRect(&tempSrcRect);
  717.         
  718.         
  719.         if (bottomClip)    // Draw bottom-left piece //
  720.         {
  721.             ForeColor(blackColor);
  722.             
  723.                 // Wrap source rect to upper-right corner //
  724.             tempSrcRect.top = srcFrameP->frameRect.top;
  725.             tempSrcRect.right = srcFrameP->frameRect.right;
  726.             tempSrcRect.bottom = srcFrameP->frameRect.top + bottomClip;
  727.             tempSrcRect.left = srcFrameP->frameRect.right - leftClip;
  728.             
  729.             FrameRect(&tempSrcRect);
  730.         }
  731.     }
  732.     
  733.     
  734.         // Draw middle section, starting at top and going down //
  735.     
  736.     if (topClip)    // Draw top middle section //
  737.     {
  738.         ForeColor(cyanColor);
  739.         
  740.             // Wrap source rect to lower middle section //
  741.         tempSrcRect.right = srcRect.right;                // Copy clipped source rect
  742.         tempSrcRect.left = srcRect.left;
  743.         tempSrcRect.bottom = srcFrameP->frameRect.bottom;
  744.         tempSrcRect.top = srcFrameP->frameRect.bottom - topClip;
  745.  
  746.         FrameRect(&tempSrcRect);
  747.     }
  748.     
  749.     
  750.             // Draw main middle section //
  751.     ForeColor(blueColor);
  752.     
  753.     tempSrcRect = srcRect;
  754.     FrameRect(&tempSrcRect);
  755.     
  756.     
  757.     if (bottomClip)    // Draw bottom middle section //
  758.     {
  759.         ForeColor(cyanColor);
  760.         
  761.             // Wrap source rect to upper middle section //
  762.         tempSrcRect.right = srcRect.right;                // Copy clipped source rect
  763.         tempSrcRect.left = srcRect.left;
  764.         tempSrcRect.top = srcFrameP->frameRect.top;
  765.         tempSrcRect.bottom = srcFrameP->frameRect.top + bottomClip;
  766.         
  767.         FrameRect(&tempSrcRect);
  768.     }
  769.     
  770.     
  771.     
  772.         // Draw right section, starting at top and going down //
  773.     
  774.     if (rightClip)
  775.     {
  776.         if (topClip)    // Draw top-right piece //
  777.         {
  778.             ForeColor(blackColor);
  779.             
  780.                 // Wrap source rect to lower-left corner //
  781.             tempSrcRect.bottom = srcFrameP->frameRect.bottom;
  782.             tempSrcRect.left = srcFrameP->frameRect.left;
  783.             tempSrcRect.right = srcFrameP->frameRect.left + rightClip;
  784.             tempSrcRect.top = srcFrameP->frameRect.bottom - topClip;
  785.             
  786.             FrameRect(&tempSrcRect);
  787.         }
  788.         
  789.         
  790.             // Draw right middle section //
  791.         
  792.         ForeColor(redColor);
  793.         
  794.             // Wrap source rect to left side //
  795.         tempSrcRect.top = srcRect.top;                // Copy clipped source rect
  796.         tempSrcRect.bottom = srcRect.bottom;
  797.         tempSrcRect.left = srcFrameP->frameRect.left;
  798.         tempSrcRect.right = srcFrameP->frameRect.left + rightClip;
  799.         
  800.         FrameRect(&tempSrcRect);
  801.         
  802.         
  803.         
  804.         if (bottomClip)    // Draw bottom-right piece //
  805.         {
  806.             ForeColor(blackColor);
  807.             
  808.                 // Wrap source rect to upper-left corner //
  809.             tempSrcRect.top = srcFrameP->frameRect.top;
  810.             tempSrcRect.left = srcFrameP->frameRect.left;
  811.             tempSrcRect.bottom = srcFrameP->frameRect.top + bottomClip;
  812.             tempSrcRect.right = srcFrameP->frameRect.left + rightClip;
  813.  
  814.             FrameRect(&tempSrcRect);
  815.         }
  816.     }
  817.     
  818.     ForeColor(blackColor);    // Set back to standard when done
  819. }
  820.  
  821.